L2-027 名人堂与代金券

题目 L2-027 名人堂与代金券

image-bb54e88b

思路分析

image-3c1659bf

主要是并列排名难处理

排名为并列时,跳跃排名,比如:

分数:100, 100, 99 → 排名为 1, 1, 3(因为两个100并列第一,下一个就是第三名)

int current_rank=1;
hall.push_back({current_rank,students[0].name,students[0].score});

第一个人默认是第1名

for(int i=1;i<students.size();i++){
	if(students[i].score != students[i-1].score){
		current_rank = i + 1;
	}
	if(current_rank > k) break;
	hall.push_back({current_rank, students[i].name, students[i].score});
}

i+1 表示的是第几个学生,因为数组从 0 开始

如果当前学生分数和前一个学生不一样,就更新排名为 i+1

如果一样分数,排名不变

由于排名可能会跳过中间值(并列情况),比如:

i 分数 当前排名
0 100 1
1 100 1
2 98 3
3 97 4

排名就形成了“并列+跳跃”的机制。

核心在于 维护原本排名和并列排名两个东西

原本排名用i递增维护 并列排名由上一个人的排名维护

代码实现

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
using ll = long long;
using ull = unsigned long long;
using PII = pair<int ,int>;
using Pll = pair<ll,ll>;
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};

struct Student{
	string name;
	int score;
	bool operator<(const Student& rhs) const{
		if(score != rhs.score)
			return score>rhs.score;
		return name<rhs.name;
	}
};

struct RankedStudent{
	int rank;
	string name;
	int score;
};

int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int n,g,k;cin>>n>>g>>k;
	vector<Student> students(n);

	int total=0;
	for(int i=0;i<n;i++){
		cin>>students[i].name>>students[i].score;
		if(students[i].score>=g)	total+=50;
		else if(students[i].score>=60)	total+=20;
	}
	cout<<total<<endl;

	sort(students.begin(),students.end());

	vector<RankedStudent> hall;

	int current_rank=1;
	hall.push_back({current_rank,students[0].name,students[0].score});
	for(int i=1;i<students.size();i++){
		if(students[i].score!=students[i-1].score){
			current_rank=i+1;
		}
		if(current_rank>k)	break;
		hall.push_back({current_rank,students[i].name,students[i].score});
	}

	for(auto v:hall){
		cout<<v.rank<<" "<<v.name<<" "<<v.score<<endl;
	}

	return 0;
}

同类题型

视频讲解


⬅️ L2-026 小字辈 🏠 00-天梯赛 ➡️ L2-028 秀恩爱分得快